#include "GY_BarChartHoriz.h"
#include <QDebug>
#include "Graphics/GY_GraphicsReflection.h"

GY_BarChartHoriz::GY_BarChartHoriz(const QString &guid, QGraphicsItem *parent) : GY_ContainerTransform(guid,this, parent)
{
    initializationPropertyInfo();
    this->setCenterPointF(m_PropertyInfoMap["Position"].propertyValue.toPointF());
    m_pTransFormGroup = new GY_TransformGroup(QString("%1_Group").arg(guid),this);
    m_ChildrensMap.insert(m_pTransFormGroup->getGuid(),m_pTransFormGroup);
    this->addToGroup(m_pTransFormGroup);
    updateDraw();
    setContainerEditPointF();
}

GY_BarChartHoriz::~GY_BarChartHoriz()
{

}

void GY_BarChartHoriz::setContainerEditPointF()
{
    this->setEditPointF("Point1",m_PropertyInfoMap["Point1"].propertyValue.toPointF());
    this->setEditPointF("Point2",m_PropertyInfoMap["Point2"].propertyValue.toPointF());
}

GY_Object *GY_BarChartHoriz::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
//        return nullptr;
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QVector<GY_Object *> childrens = m_pTransFormGroup->getOrderChildrens();
    int childrensSize = childrens.size();
    for(int i=0;i<childrensSize;i++) {
//        if(childrens[i]->copyItem() == nullptr) {
//            qDebug()<<childrens[i]->getGuid()<<"isEmpty";
//            continue;
//        }
        ((GY_ContainerTransform*)pObj)->addItem(childrens[i]->copyItem());
    }

    QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
    while (iterProperty != m_PropertyInfoMap.end()) {
        if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
        }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
            ++iterProperty;
            continue;
        }else {
            pObj->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
        }
        ++iterProperty;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

bool GY_BarChartHoriz::addItem(GY_Object *pItem)
{
    m_pTransFormGroup->addItem((GY_Object*)pItem);
    updateDraw();
    return true;
}

bool GY_BarChartHoriz::removItem(const QString &guid)
{
    return m_pTransFormGroup->removItem(guid);
}

bool GY_BarChartHoriz::removItem(const GY_Object *pItem)
{
    bool remove = m_pTransFormGroup->removItem((GY_Object*)pItem);
    this->GY_ContainerTransform::removItem((GY_Object*)pItem);
    updateDraw();
    return remove;
}

void GY_BarChartHoriz::initializationPropertyInfo()
{
    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    //位置
    GY_PropertyInfo positonPropertyInfo(this);
    positonPropertyInfo.propertyName="Position";
    positonPropertyInfo.propertyValue=QPointF(0,0);
    positonPropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    positonPropertyInfo.propertyType = PointPropertyType;
    positonPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updatePosition;
    m_PropertyInfoMap.insert(positonPropertyInfo.propertyName,positonPropertyInfo);
    m_PropertyInfoMap[positonPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo valuePropertyInfo(this);
    valuePropertyInfo.propertyName="Value";
    valuePropertyInfo.propertyValue=1;
    valuePropertyInfo.updateType = Update|OrdinaryAttributes;
    valuePropertyInfo.propertyType = QrealPropertyType;
    valuePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updateValue;
    m_PropertyInfoMap.insert(valuePropertyInfo.propertyName,valuePropertyInfo);
    m_PropertyInfoMap[valuePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo startValuePropertyInfo(this);
    startValuePropertyInfo.propertyName="StartValue";
    startValuePropertyInfo.propertyValue=0;
    startValuePropertyInfo.updateType = Update|OrdinaryAttributes;
    startValuePropertyInfo.propertyType = QrealPropertyType;
    startValuePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updateStartValue;
    m_PropertyInfoMap.insert(startValuePropertyInfo.propertyName,startValuePropertyInfo);
    m_PropertyInfoMap[startValuePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo EndValuePropertyInfo(this);
    EndValuePropertyInfo.propertyName="EndValue";
    EndValuePropertyInfo.propertyValue=1;
    EndValuePropertyInfo.updateType = Update|OrdinaryAttributes;
    EndValuePropertyInfo.propertyType = QrealPropertyType;
    EndValuePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updateEndValue;
    m_PropertyInfoMap.insert(EndValuePropertyInfo.propertyName,EndValuePropertyInfo);
    m_PropertyInfoMap[EndValuePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo StartPointPropertyInfo(this);
    StartPointPropertyInfo.propertyName="StartPoint";
    StartPointPropertyInfo.propertyValue=0;
    StartPointPropertyInfo.updateType = Update|OrdinaryAttributes;
    StartPointPropertyInfo.propertyType = QrealPropertyType;
    StartPointPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updateStartPoint;
    m_PropertyInfoMap.insert(StartPointPropertyInfo.propertyName,StartPointPropertyInfo);
    m_PropertyInfoMap[StartPointPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo EndPointPropertyInfo(this);
    EndPointPropertyInfo.propertyName="EndPoint";
    EndPointPropertyInfo.propertyValue=100;
    EndPointPropertyInfo.updateType = Update|OrdinaryAttributes;
    EndPointPropertyInfo.propertyType = QrealPropertyType;
    EndPointPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updateEndPoint;
    m_PropertyInfoMap.insert(EndPointPropertyInfo.propertyName,EndPointPropertyInfo);
    m_PropertyInfoMap[EndPointPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo point1PropertyInfo(this);
    point1PropertyInfo.propertyName="Point1";
    point1PropertyInfo.propertyValue=QPointF(0,0);
    point1PropertyInfo.updateType = NotUpdate;
    point1PropertyInfo.propertyType = PointPropertyType;
    point1PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updatePoint;
    m_PropertyInfoMap.insert(point1PropertyInfo.propertyName,point1PropertyInfo);
    m_PropertyInfoMap[point1PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo point2PropertyInfo(this);
    point2PropertyInfo.propertyName="Point2";
    point2PropertyInfo.propertyValue=QPointF(100,0);
    point2PropertyInfo.updateType = NotUpdate;
    point2PropertyInfo.propertyType = PointPropertyType;
    point2PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_BarChartHoriz::updatePoint;
    m_PropertyInfoMap.insert(point2PropertyInfo.propertyName,point2PropertyInfo);
    m_PropertyInfoMap[point2PropertyInfo.propertyName].setConnect();

}

void GY_BarChartHoriz::updateDraw()
{
    qreal startPoint = m_PropertyInfoMap["StartPoint"].propertyValue.toReal();
    qreal endPoint = m_PropertyInfoMap["EndPoint"].propertyValue.toReal();
    qreal value = m_PropertyInfoMap["Value"].propertyValue.toReal();
    qreal startValue = m_PropertyInfoMap["StartValue"].propertyValue.toReal();
    qreal endValue = m_PropertyInfoMap["EndValue"].propertyValue.toReal();
    if((value-startValue)<=0) {
        this->setVisible(false);
    }else {
        this->setVisible(true);
    }
    qreal proportion = (value-startValue)/(endValue-startValue);
    if(!qIsInf((proportion*endPoint)/(m_pTransFormGroup->childrenBoundingRect().width()))) {
        m_pTransFormGroup->setScaleX((proportion*endPoint)/(m_pTransFormGroup->childrenBoundingRect().width()));
    }
}

bool GY_BarChartHoriz::updatePosition(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    //setpos设置为父级坐标
    QPointF point = value.toPointF();
    if(this->parentItem()) {
        point = this->mapToParent(this->mapFromScene(value.toPointF()));
    }
    this->setPos(point);
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
//    this->setCenterPointF(this->mapFromScene(value.toPointF()));
    return true;
}

bool GY_BarChartHoriz::updateValue(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toReal();
    updateDraw();
    return true;
}

bool GY_BarChartHoriz::updateStartValue(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toReal();
    updateDraw();
    return true;
}

bool GY_BarChartHoriz::updateEndValue(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toReal();
    updateDraw();
    return true;
}

bool GY_BarChartHoriz::updateStartPoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    QPointF point1;
    point1.setX(value.toReal());
    point1.setY(0);
    m_PropertyInfoMap["Point1"].propertyValue = point1;
    this->setEditPointF("Point1",point1);
    updateDraw();
    return true;
}

bool GY_BarChartHoriz::updateEndPoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    QPointF point2;
    point2.setX(value.toReal());
    point2.setY(0);
    m_PropertyInfoMap["Point2"].propertyValue = point2;
    this->setEditPointF("Point2",point2);
    updateDraw();
    return true;
}

bool GY_BarChartHoriz::updatePoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    if(name == "Point1") {
        QPointF point1 = this->mapFromScene(value.toPointF());
        m_PropertyInfoMap["StartPoint"].propertyValue = point1.x();
        point1.setY(0);
        m_PropertyInfoMap["Point1"].propertyValue=point1;
        this->setEditPointF(name,point1);
        updateDraw();
        return  true;
    }else if(name == "Point2") {
        QPointF point2 = this->mapFromScene(value.toPointF());
        m_PropertyInfoMap["EndPoint"].propertyValue = point2.x();
        point2.setY(0);
        m_PropertyInfoMap["Point2"].propertyValue=point2;
        this->setEditPointF(name,point2);
        updateDraw();
        return true;
    }
    return false;
}
